#!/usr/bin/env bash

# Script that lists bookmarks from a Firefox profile directory without Firefox.
# Should work with IceCat, IceWeasel, ABrowser, LibreWolf etc.
# by Adnan Shameem (adnan360); License: MIT (Expat)
#
# Usage:
# - Make sure you have sqlite installed on your system
# - Edit the 'profiles_path=' line below to match your browser/path
# - Run the script: ./firefox-bookmarks.sh

# Extracts and prints bookmarks from a Firefox or based browser (such as IceCat, ABrowser, LibreWolf etc.)
# Params:
#   - $1: Profile dir, e.g. "~/.librewolf/k2fdb24c.default"
function extract_bookmarks() {
	places_db=$(find "${1}/" -name "places.sqlite")
	# Ref: https://www.sqlite.org/uri.html#the_uri_path
	places_db=$(echo "$places_db" | sed 's|?|%3f|' | sed 's|#|%23|' | sed 's|\/\/|\/|')

	# Ref:
	# https://wiki.mozilla.org/Places/Places_SQL_queries_best_practices#Querying_multiple_tables
	# https://gist.github.com/iafisher/d624c04940fa46c6d9afb26cb1bf222a
	sql_query="SELECT b.title, h.url FROM moz_places h JOIN moz_bookmarks b ON h.id = b.fk WHERE b.type = 1 AND b.title IS NOT NULL"

	if [ -z "$(command -v sqlite3)" ]; then
		echo 'Error: sqlite3 binary is not found on system. Maybe sqlite is not installed.'; exit 8723
	fi

	# Ref: https://sleeplessbeastie.eu/2014/01/02/how-to-open-firefox-bookmarks-from-openbox-menu/
	# "immutable=1" is used as a workaround to access locked database. Ref:
	# https://www.sqlite.org/uri.html#recognized_query_parameters
	sqlite3 -separator '^' "file:${places_db}?immutable=1" "$sql_query" | while IFS=^ read title url; do
		echo "$title -> $url"
	done
}


# Enter the dir where the file profiles.ini lives
# - IceCat: "$HOME/.mozilla/icecat/"
# - Firefox/IceWeasel: "$HOME/.mozilla/firefox/"
# - ABrowser (Trisquel): "$HOME/.mozilla/abrowser/"
# - LibreWolf: "$HOME/.librewolf/"
profiles_path="$HOME/.mozilla/icecat/"

# Pick the profile dir
if [ -z "$(grep 'Default=' "${profiles_path}/profiles.ini")" ]; then
	profile_dir_name=$(sed -n -e 's|Path=\(.*\)|\1|p' "${profiles_path}/profiles.ini" | head -n 1)
else
	# "{8,}" is to avoid "Default=1" line. This looks for a value of 8 or more
	# characters. 8 is the usual profile dir name length.
	profile_dir_name=$(sed -n -e 's|Default=\(.\{8,\}\)|\1|p' "${profiles_path}/profiles.ini" | head -n 1)
fi
# Determine the full profile dir
profile_dir="${profiles_path}/${profile_dir_name}"

# Finally, show the bookmarks!
extract_bookmarks "$profile_dir"
